<?php
declare(strict_types=1);

/**
 * This is my open source code, please do not use it for commercial applications.
 * For the full copyright and license information,
 * please view the LICENSE file that was distributed with this source code
 *
 * @author Yuandong<837215079@qq.com>
 * @link   https://github.com/gzydong/hyperf-chat
 */

namespace App\Controller;

use Hyperf\Redis\Redis;
use App\Model\Group\Group;
use App\Service\Group\GroupService;
use Hyperf\Di\Annotation\Inject;
use App\Cache\SocketRoom;
use App\Service\Group\GroupMemberService;
use App\Service\Message\ReceiveHandleService;
use App\Constant\TalkEventConstant;
use Hyperf\Contract\OnCloseInterface;
use Hyperf\Contract\OnMessageInterface;
use Hyperf\Contract\OnOpenInterface;
use Swoole\Http\Request;
use Swoole\Websocket\Frame;
use Swoole\Http\Response;
use Swoole\WebSocket\Server;
use App\Service\SocketClientService;
use App\Event\TalkEvent;

/**
 * Class WebSocketController
 *
 * @package App\Controller
 */
class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
    /**
     * @Inject
     * @var SocketClientService
     */
    protected $client;

    /**
     * @Inject()
     * @var Redis
     */
    private $redis;

    /**
     * @Inject
     * @var ReceiveHandleService
     */
    protected $receiveHandle;

    /**
     * @var GroupService
     */
    private $groupService;

    /**
     * 连接创建成功回调事件
     *
     * @param Response|Server $server
     * @param Request         $request
     */
    public function onOpen($server, Request $request): void
    {

        $server->push($request->fd, json_encode(['event' => 'connect']));


        stdout_log()->notice("用户连接信息  | fd:{$request->fd} 时间：" . date('Y-m-d H:i:s'));
    }

    /**
     * 消息接收回调事件
     *
     * @param Response|Server $server
     * @param Frame           $frame
     */
    public function onMessage($server, Frame $frame): void
    {
        info('result', [$frame->data]);
        $result = json_decode($frame->data, true);


        // 判断是否为心跳检测
        if ($result['event'] == 'heartbeat') {
            $server->push($frame->fd, json_encode(['event' => "heartbeat", 'content' => "pong"]));
            return;
        }

        info('message', $result);
        info('event', [ReceiveHandleService::EVENTS]);
        if (!isset(ReceiveHandleService::EVENTS[$result['event']])) {
            return;
        }

        // 回调处理
        call_user_func_array([$this->receiveHandle, ReceiveHandleService::EVENTS[$result['event']]], [
            $server, $frame, $result['data']
        ]);
    }

    /**
     * 连接创建成功回调事件
     *
     * @param Response|\Swoole\Server $server
     * @param int                     $fd
     * @param int                     $reactorId
     */
    public function onClose($server, int $fd, int $reactorId): void
    {

        // $activityId = data_get($this->redis->hGet(config('cache.prefix')."SCREEN_SOCKET", (string)$fd), '0', ''); // 错误的
        $activityId = $this->redis->hGet(config('cache.prefix')."SCREEN_SOCKET", (string)$fd) ?: '';
        info('close', [$fd, $activityId]);
        if (!empty($activityId)) {
            $this->redis->hDel(config('cache.prefix')."SCREEN_SOCKET", (string)$fd);
            $this->redis->sRem(config('cache.prefix')."SCREEN_SOCKET_$activityId", $fd);
            $this->redis->del(config('cache.prefix')."SCREEN_ACTIVITY_$activityId");
        }

        $screenId = $this->redis->hGet(config('cache.prefix')."SCREEN_ID_SOCKET", (string)$fd) ?: '';
        info('close_player_screen', [$fd, $screenId]);
        if (!empty($screenId)) {
            $this->redis->hDel(config('cache.prefix')."SCREEN_ID_SOCKET", (string)$fd);
            $this->redis->sRem(config('cache.prefix')."SCREEN_ID_SOCKET_$screenId", $fd);
        }
        
    }
}
